package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.service.HotArticleService;
import com.heima.common.constants.ArticleConstants;
import com.heima.common.redis.CacheService;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.vos.HotArticleVo;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Slf4j
@Transactional
public class HotArticleServiceImpl implements HotArticleService {
    @Autowired
    private ApArticleMapper apArticleMapper;
    @Autowired
    private CacheService cacheService;

    /**
     * 计算热点文章
     */
    @Override
    public void computerHotArticle() {
        //1、先取出前五天的文章
        //1.1、先计算得出前五天的时间
        Date dateParam = DateTime.now().minusDays(5).toDate();
        //1.2、查询数据库
        List<ApArticle> apArticleList = apArticleMapper.findArticleListLast5Days(dateParam);
        //2、计算每篇文章的分值
        //2.1、stream流处理数据
        List<HotArticleVo> hotArticleVos = apArticleList.stream().map(apArticle -> {
            //创建vo对象
            HotArticleVo hotArticleVo = new HotArticleVo();
            //属性拷贝
            BeanUtils.copyProperties(apArticle, hotArticleVo);
            //计算分值
            int score = computeScore(apArticle);
            //补充属性
            hotArticleVo.setScore(score);
            //返回对象
            return hotArticleVo;
        }).collect(Collectors.toList());
        //2.2、按分数倒序排序 先正序再反转 再取前30个数据
        hotArticleVos = hotArticleVos.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).limit(30).collect(Collectors.toList());
        //2.3、得到所有频道id集合 需要去重
        List<Integer> channelIds = apArticleList.stream().map(ApArticle::getChannelId).distinct().collect(Collectors.toList());
        //3、为每个频道缓存30条热点文章 不需要远程调用（脱裤子放屁）
        //3.1、遍历拿到的频道id集合
        for (Integer channelId : channelIds) {
            //3.2、拿到频道id对应的热点文章
            List<HotArticleVo> collect = hotArticleVos.stream().filter(hotArticleVo -> hotArticleVo.getChannelId().equals(channelId)).collect(Collectors.toList());
            //3.3、加入redis对应频道id的 转成json对象
            cacheService.set(ArticleConstants.HOT_ARTICLE_FIRST_PAGE + channelId, JSON.toJSONString(collect));
        }
        //4、推荐直接放所有频道分数前30的
        Stream<HotArticleVo> collect = hotArticleVos.stream().sorted(Comparator.comparing(HotArticleVo::getScore).reversed()).limit(30);
        //4.1、加入redis中的推荐
        cacheService.set(ArticleConstants.HOT_ARTICLE_FIRST_PAGE + ArticleConstants.DEFAULT_TAG, JSON.toJSONString(collect));
    }

    /**
     * 计算每篇文章的分值
     *
     * @param apArticle
     * @return
     */
    private int computeScore(ApArticle apArticle) {
        int score = 0;
        //阅读 权重为1
        if (apArticle.getViews() != null) {
            score += apArticle.getViews();
        }
        //点赞 权重为3
        if (apArticle.getLikes() != null) {
            score += apArticle.getLikes() * ArticleConstants.HOT_ARTICLE_LIKE_WEIGHT;
        }
        //评论 权重为5
        if (apArticle.getComment() != null) {
            score += apArticle.getComment() * ArticleConstants.HOT_ARTICLE_COMMENT_WEIGHT;
        }
        //收藏 权重为8
        if (apArticle.getCollection() != null) {
            score += apArticle.getCollection() * ArticleConstants.HOT_ARTICLE_COLLECTION_WEIGHT;
        }
        return score;
    }
}
